/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.rpc.remote.grpc;

import io.grpc.ClientInterceptor;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.Metadata;
import io.grpc.stub.MetadataUtils;
import io.iec.edp.caf.rpc.api.grpc.GrpcInvokeServiceGrpc;
import io.iec.edp.caf.rpc.api.grpc.GrpcRequest;
import io.iec.edp.caf.rpc.api.grpc.GrpcResponse;
import io.iec.edp.caf.rpc.api.grpc.utils.GrpcClientBuilder;
import io.iec.edp.caf.rpc.api.grpc.utils.GrpcServiceFactory;
import io.iec.edp.caf.rpc.api.grpc.variable.GrpcVariable;
import lombok.extern.slf4j.Slf4j;

import java.net.MalformedURLException;
import java.util.Map;

/**
 * Caf的gRpc客户端构造器
 */
@Slf4j
public class CafGrpcChannel {

    private GrpcInvokeServiceGrpc.GrpcInvokeServiceBlockingStub blockingStub;

    ManagedChannel managedChannel = null;
    /**
     * @param host gRPC服务的主机名
     * @param port gRPC服务的端口
     */
    public CafGrpcChannel(String host, int port) {

        ManagedChannelBuilder<?> channelBuilder = GrpcClientBuilder.getChannelBuilder(host,port);
        registerInterceptors(channelBuilder);
        managedChannel = channelBuilder.build();
        blockingStub = GrpcInvokeServiceGrpc.newBlockingStub(managedChannel);
    }

    public CafGrpcChannel(String remoteUrl) throws MalformedURLException {
        ManagedChannelBuilder<?> channelBuilder = GrpcClientBuilder.getChannelBuilder(remoteUrl);
        registerInterceptors(channelBuilder);
        managedChannel = channelBuilder.build();
        blockingStub = GrpcInvokeServiceGrpc.newBlockingStub(managedChannel);
    }

    public boolean ready(){
        return managedChannel!=null&&blockingStub!=null;
    }

    private void registerInterceptors(ManagedChannelBuilder<?> channelBuilder){
        Map<String,Object> interceptors = GrpcServiceFactory.getClientFilter(GrpcVariable.CAF_GRPC_MODE_DEFAULT);
        if(interceptors!=null){
            interceptors.forEach((beanName,bean)->{
                GrpcClientBuilder.addClientInterceptor(channelBuilder,(ClientInterceptor) bean);
                log.info(beanName + " has already registered into grpcClientInterceptors.");
            });
        }
    }

    //添加header
    public void attachHeaders(Map<String,String> headers){
        Metadata metadata = new Metadata();
        headers.forEach((key,val)->{
            metadata.put(Metadata.Key.of(key,Metadata.ASCII_STRING_MARSHALLER),val);
        });
        blockingStub = MetadataUtils.attachHeaders(blockingStub,metadata);
    }

    //重写生成stub
    public void reset(){
        blockingStub = GrpcInvokeServiceGrpc.newBlockingStub(managedChannel);
    }

    public String invoke(String svcId, Map<String, String> params, String context) {
        GrpcRequest req = GrpcRequest.newBuilder()
                .setServiceId(svcId)
                .setContext(context)
                .putAllParams(params)
                .build();
        GrpcResponse resp = blockingStub.grpcRemoteInvoke(req);

        return resp.getMessage();
    }

    public void shutDown(){
        this.managedChannel.shutdown();
    }

}
